package org.jheuristics.ga.scalers;

import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

import org.jheuristics.ga.multiObjective.MultiObjectiveFitness;

/**
 * TODO
 *
 * @author Marcell Manfrin, marcell@ourgrid.org, Jan 9, 2006
 */
public class RawFitnessScaler implements FitnessScaler {

	/**
	 * TODO
	 *
	 * @param fitness
	 * @return
	 * @see org.jheuristics.ga.scalers.FitnessScaler#scale(java.lang.Comparable[])
	 */
	public double[] scale(Comparable[] fitness) {
        if (null == fitness) {
            // TODO: ERROR MSG
            throw new NullPointerException();
        }
        if (0 == fitness.length) {
            // TODO: ERROR MSG
            throw new IllegalArgumentException();
        }
        MultiObjectiveFitness[] multiFitness = new MultiObjectiveFitness[fitness.length];
        for (int i = 0; i < fitness.length; i++) {
            if (null == fitness[i]) {
                // TODO: ERROR MSG
                throw new NullPointerException();
            }
            if (!(fitness[i] instanceof MultiObjectiveFitness)) {
                // TODO: ERROR MSG
                throw new ClassCastException();
            } else {
            	multiFitness[i] = (MultiObjectiveFitness) fitness[i];
            }
        }
        Set[] dominatedBy = new Set[multiFitness.length];
        Set[] dominate = new Set[multiFitness.length];
        for (int i = 0; i < dominatedBy.length; i++) {
        	dominatedBy[i] = new HashSet();
        	dominate[i] = new HashSet();
        }
        for (int i = 0; i < multiFitness.length; i++) {
        	for (int j = i + 1; j < multiFitness.length; j++) {
        		int value = multiFitness[i].relatesTo(multiFitness[j]);
        		if (0 > value) {
        			dominate[j].add(new Integer(i));
        			dominatedBy[i].add(new Integer(j));
        		} else if (0 < value) {
        			dominate[i].add(new Integer(j));
        			dominatedBy[j].add(new Integer(i));
        		}
        	}
        }

        double result[] = new double[multiFitness.length];
        for (int i = 0; i < multiFitness.length; i++) {
        	result[i] = 0.0;
        	for (Iterator it = dominatedBy[i].iterator(); it.hasNext(); ) {
        		int individual = ((Integer) it.next()).intValue();
        		result[i] += dominate[individual].size();
        	}
        }
		return result;
	}

}
